home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 1
/
Nebula One.iso
/
Educational
/
Ortografie
/
Ortografie.app
/
PlayerControl.m
< prev
next >
Wrap
Text File
|
1995-09-01
|
9KB
|
390 lines
// Copyright (95) by melonSoft Ralf Suckow Berlin, All Rights Reserved
//
// You may freely copy, distribute, and reuse the code in this example.
// Ralf Suckow disclaims any warranty of any kind, expressed or
// implied, as to its fitness for any particular use.
#import "PlayerControl.h"
#import <strings.h>
#import <sound/accesssound.h>
#import <sound/performsound.h>
#define SAVEDFILENAME "Library/Ortografie/words.orth"
#define CREATESAVEDFILEDIR "mkdirs ~/Library/Ortografie"
@implementation PlayerControl
- appDidInit:sender
{
NXTypedStream * infile;
char filename[1024];
// looking up an existing file in users library
sprintf (filename, "%s/%s", NXHomeDirectory (), SAVEDFILENAME);
infile = NXOpenTypedStreamForFile (filename, NX_READONLY);
if (!infile) {
// creating new sound list
sounds = [[List alloc] init];
}
else {
// loading old file
sounds = NXReadObject (infile);
// update browser
[browser loadColumnZero];
NXCloseTypedStream (infile);
}
currentSound = nil;
askingFor = nil;
previousAsked = nil;
SNDReserve(SND_ACCESS_IN | SND_ACCESS_OUT, 0);
return self;
}
- next:sender
{
id next;
if ([sounds count] == 0) {
#define NEXT_WORD NXLocalizedString ("NextWord", NULL, goto next word action)
#define NO_WORDS NXLocalizedString ("NoWords", NULL, no words found problem)
NXRunAlertPanel (NEXT_WORD, NO_WORDS, NULL, NULL, NULL);
return nil;
}
if (askingFor)
[self playSoundNamed:"erst_loesen"];
else {
// looking for a new word to ask for
if ([sounds count] == 1)
next = [sounds objectAt:0];
else
while ((next = [sounds objectAt:random() % [sounds count]])
== previousAsked)
;
askingFor = next;
[self same:self];
}
return self;
}
- same:sender
{
// ask for same work
if (askingFor) {
switch (random () % 3) {
case 0: [self playSoundNamed:"schreibe_wort"]; break;
case 1: [self playSoundNamed:"schreibe_bitte"]; break;
case 2: [self playSoundNamed:"naechstes_wort"]; break;
}
[self playSound:askingFor];
[[text setStringValue:""] selectText:self];
}
else
[self playSoundNamed:"nichts_gesagt"];
return self;
}
- help:sender
{
if (askingFor) {
[rightText setStringValue:[askingFor name]];
[rightPanel makeKeyAndOrderFront:self];
[NXApp runModalFor:rightPanel];
[rightPanel orderOut:self];
}
else
[self playSoundNamed:"druecke_next"];
return self;
}
- closeHelp:sender
{
[NXApp stopModal];
return self;
}
- ready:sender
{
// check word
if (askingFor) {
if (!strcmp ([askingFor name], [text stringValue])) {
switch (random () % 5) {
case 0: [self playSoundNamed:"sehr_gut"]; break;
case 1: [self playSoundNamed:"gut_gemacht"]; break;
case 2: [self playSoundNamed:"einwandfrei"]; break;
case 3: [self playSoundNamed:"otlitschno"]; break;
case 4: [self playSoundNamed:"richtig"]; break;
}
if ([askingFor info])
* (int *) [askingFor info] += 1;
previousAsked = askingFor;
askingFor = nil;
}
else {
switch (random () % 4) {
case 0: [self playSoundNamed:"falsch"]; break;
case 1: [self playSoundNamed:"nochmal"]; break;
case 2: [self playSoundNamed:"denk_nach"]; break;
case 3: [self playSoundNamed:"noch_nicht"]; break;
}
if ([askingFor info])
* (int *) [askingFor info] = 0;
}
[[browser loadColumnZero] display];
}
else
[self playSoundNamed:"druecke_next"];
return self;
}
- add:sender
{
int row;
Sound * sound;
const char * name;
if (!strcmp ([newText stringValue], "")) {
#define ADD_WORD NXLocalizedString ("AddingWord", NULL, add word action)
#define NO_NAME NXLocalizedString ("TypeIn", NULL, word not typed in problem)
NXRunAlertPanel (ADD_WORD, NO_NAME, NULL, NULL, NULL);
return nil;
}
// looking for existing sound
name = [newText stringValue];
for (row = 0; row < [sounds count]; row ++)
if (!strcmp (name, [[sounds objectAt:row] name]))
break;
if (row != [sounds count]) { // gefunden
#define DUP_WORD NXLocalizedString ("IsInList", NULL, duplication problem)
#define AHA_ANSWER NXLocalizedString ("Indeed", NULL, a positive answer)
NXRunAlertPanel (ADD_WORD, DUP_WORD, AHA_ANSWER, NULL, NULL);
[browser scrollColumnToVisible:row];
return nil;
}
if (!(sound = [[Sound alloc] init])) {
#define NO_NEW_SND NXLocalizedString ("NoNewSnd", NULL, no new sound problem)
NXRunAlertPanel (ADD_WORD, NO_NEW_SND, NULL, NULL, NULL);
return nil;
}
[sound setName:name];
[sounds addObject:sound];
[browser loadColumnZero];
currentSound = sound;
[[browser matrixInColumn:0] selectCellAt:row :0];
[browser scrollColumnToVisible:row];
[newText selectText:self];
return self;
}
- remove:sender
{
if (currentSound)
[self stop:self];
[[sounds removeObject:currentSound] free];
currentSound = nil;
[newText setStringValue:""];
[browser loadColumnZero];
return self;
}
- browserClicked:sender
{
int row;
row = [[browser matrixInColumn:0] selectedRow];
currentSound = [sounds objectAt:row];
[newText setStringValue:[currentSound name]];
return self;
}
- play:sender
{
if (currentSound)
[self playSound:currentSound];
return self;
}
- stop:sender
{
if (currentSound /* && [recordButton state] */)
[currentSound stop:sender];
return self;
}
- record:sender
{
// two attempts for avoiding Mach Kernel Errors
int err;
if (currentSound) {
[recordButton setEnabled:NO];
[playButton setEnabled:NO];
// The second recording doesn't work.
// The structure, in fact, is emptied with deleteSamples,
// but when you record again, a part of the
// old sound is intermixed/overlayed with the new.
// I don't have an idea what to do.
[currentSound deleteSamples];
if ([[currentSound setDelegate:self] record])
if (err = [currentSound record]) {
#define RECORDING NXLocalizedString ("Recording", NULL, recording action)
#define SOUND_ERROR NXLocalizedString ("SndError", NULL, sound error: description)
NXRunAlertPanel (RECORDING, SOUND_ERROR, NULL, NULL, NULL,
SNDSoundError(err));
[self didRecord:self];
}
}
else {
#define SELECT_ENTER NXLocalizedString ("SelectOrEnter", NULL, no word selected to be recorded)
NXRunAlertPanel (RECORDING, SELECT_ENTER, NULL, NULL, NULL);
[recordButton setState:0];
}
return self;
}
- playSound:sound
/*
** Synchroneous Playing -- two attempts for avoiding Mach Kernel Errors
*/
{
SNDSoundStruct * s;
int err;
s = [sound soundStruct];
err = SNDStartPlaying (s, 1, 0, 0, SND_NULL_FUN, SND_NULL_FUN);
if (err)
err = SNDStartPlaying (s, 1, 0, 0, SND_NULL_FUN, SND_NULL_FUN);
if (err)
#define PLAYBACK NXLocalizedString ("Playback", NULL, playback action)
NXRunAlertPanel (PLAYBACK, SOUND_ERROR, NULL, NULL, NULL,
SNDSoundError(err));
else
SNDWait (1);
return self;
}
- didRecord:sender
{
if ([recordButton state]) {
[[recordButton setState:0] setEnabled:YES];
[playButton setEnabled:YES];
}
return self;
}
- hadError:sender
{
int err;
err = [[sender soundBeingProcessed] processingError];
#define PROBLEM NXLocalizedString ("Problem", NULL, problematic action)
NXRunAlertPanel (PROBLEM, SOUND_ERROR, NULL, NULL, NULL,
SNDSoundError(err));
[self didRecord:self];
return self;
}
- save:sender
{
NXTypedStream * outfile;
char filename[1024];
sprintf (filename, "%s/%s", NXHomeDirectory (), SAVEDFILENAME);
outfile = NXOpenTypedStreamForFile (filename, NX_WRITEONLY);
if (!outfile) {
system (CREATESAVEDFILEDIR);
outfile = NXOpenTypedStreamForFile (filename, NX_WRITEONLY);
}
if (!outfile)
#define SAVING NXLocalizedString ("Saving", NULL, saving action)
#define CANNOT_OPEN NXLocalizedString ("CannotOpen", NULL, cannot open: filename)
NXRunAlertPanel (SAVING, CANNOT_OPEN, NULL, NULL, NULL, filename);
else {
NXWriteRootObject (outfile, sounds);
NXCloseTypedStream (outfile);
}
return self;
}
- playSoundNamed:(const char *)name
{
return [self playSound:[Sound findSoundFor:name]];
}
// browser delegate methods (a very lazy delegate)
- (int)browser:sender getNumRowsInColumn:(int)column
{
if (column == 0)
return [sounds count];
else
return 0;
}
- browser:sender loadCell:cell atRow:(int)row inColumn:(int)column
{
id sound;
char toDisplay[1024];
int * infoPtr;
sound = [sounds objectAt:row];
infoPtr = (int *) [sound info];
sprintf (toDisplay, "%-3d %s", infoPtr? *infoPtr : 0, [sound name]);
[[[[cell setLoaded:YES]
setLeaf:YES]
setStringValue:toDisplay]
setEnabled:YES];
return self;
}
@end